using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml.Linq;

namespace TD.TheGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class ActionScreen : DrawableGameComponent
    {
        SpriteBatch spriteBatch;
        Texture2D background;

        Castle castle;
        PlayerComponent playerComponent;
        LevelComponent levelComponent;
        KeyBoardInput keyboardInput;
        Age age;
        Age oldAge;
        private bool hitCastle;
        private int fenceTime = 2000;
        private int currentFenceTime = 0;
        public ActionScreen(Game game) : 
            base(game)
        {
            this.Enabled = false;
            this.Visible = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        public override void Initialize()
        {
            //texture = Content.Load<Texture2D>("BackGround/alienmetal");
            // TODO: use this.Content to load your game content here
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            //Add SpriteBatch Servies
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Game.Services.AddService(typeof(SpriteBatch), spriteBatch);

            //Add Keyboard Services
            keyboardInput = new KeyBoardInput();
            Game.Services.AddService(typeof(KeyBoardInput), keyboardInput);

            //Add Castle
            castle = new Castle(Game);
            Game.Components.Add(castle);
            Game.Services.AddService(typeof(Castle), castle);

            //Add player
            playerComponent = new PlayerComponent(Game);
            Game.Services.AddService(typeof(PlayerComponent), playerComponent);
            Game.Components.Add(playerComponent);

            //Add Level
            levelComponent = new LevelComponent(Game);
            Game.Services.AddService(typeof(LevelComponent), levelComponent);
            Game.Components.Add(levelComponent);
            age = levelComponent.CurrentAge;
            

            // Add the HUD
            TD.Interface.HUD hud = new Interface.HUD((Game1)Game);
            Game.Components.Add(hud);

            TextureManager manager = (TextureManager)Game.Services.GetService(typeof(TextureManager));
            manager.LoadAsset("level\\level_background");
            background = manager.UseAsset("level\\level_background");

            // Have to make explicit calls to make the components coup properly.
            OnEnabledChanged(this, EventArgs.Empty);
            OnVisibleChanged(this, EventArgs.Empty);

            base.LoadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
            if (background != null)
            {
                background.Dispose();
                background = null;
            }
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            CollisionDetection(gameTime);
            UpdateTexturesPerAge();

            //bulletSprite.Update(gameTime);
            //Console.WriteLine(playerComponent.bullets[0].BoundingRect);

            //double foreach loop
            //if (playerComponent.bullets[0].BoundingRect.Intersects(enemyComponent.alien.BoundingRect))
            //{
            //    playerComponent.bullets[0].Active = false;
            //    enemyComponent.alien.isCollide = true;
            //}

            //foreach (var item in collection)
            //{
            //    foreach (var item in collection)
            //    {
                    
            //    }
            //}
        }

        public void CollisionDetection(GameTime gameTime)
        {
            foreach (var enemy in levelComponent.currentEnemys)
            {
                //check the way of walking of the enemy
                foreach (var castlePart in castle.castleParts)
                {
                    // if enemy walk against the building
                    if (enemy.Intersects(castlePart.BoundingRectangle) && castlePart.Active)
                    {
                        enemy.Speed = 0;
                        break;
                    }
                    else if (castle.currentFence.Intersects(enemy.BoundingRectangle) && castle.currentFence.Active == true)
                    {
                        enemy.Speed = 0;
                        break;
                    }
                    else
                    {
                        if (enemy.State != SpriteEnumState.Die)
                        {
                            enemy.Speed = enemy.MaxSpeed;
                        }
                    }
                }

                //Check if enemy is behind the castle
                if (enemy.position.X < 0)
                {
                    levelComponent.GameOver = true;
                }

                //check collision enemy/castle
                foreach (var castlePart in castle.castleParts)
                {
                    if (castlePart.Intersects(enemy.BoundingRectangle) && castlePart.Active && enemy.State != SpriteEnumState.Die)
                    {
                        enemy.State = SpriteEnumState.Shoot;
                        if (enemy.endSprite)
                        {
                            //Do Damage
                            castlePart.Health -= enemy.Damage;
                        }
                    }
                }
                int count = 0;

                //check if enemy collides with castleArrows
                foreach (var arrow in castle.Arrows)
                {
                    count++;
                    if (arrow.Intersects(enemy.BoundingRectangle))
                    {
                        enemy.Health = 0;
                        arrow.Reset();
                    }
                }

                //check for collision with fences!
                if (castle.currentFence.Intersects(enemy.BoundingRectangle) && castle.currentFence.Active)
                {
                    if (castle.currentFence.Health >= 0)
                    {
                        if (enemy.endSprite)
                        {
                            castle.currentFence.Health -= enemy.Damage;
                        }
                        currentFenceTime += gameTime.ElapsedGameTime.Milliseconds;
                        if (currentFenceTime > fenceTime)
                        {
                            currentFenceTime = 0;
                            enemy.Health -= castle.currentFence.Damage;
                        }
                    }
                }



                //check collision arrow/enemy
                foreach (var arrow in playerComponent.arrows)
                {
                    if (arrow.Intersects(enemy.BoundingRectangle))
                    {
                        if (enemy.State == SpriteEnumState.Normal || enemy.State == SpriteEnumState.Shoot)
                        {
                            arrow.Reset();
                            levelComponent.Points += enemy.Health;
                            enemy.Health -= arrow.Damage;
                        }
                    }
                }
            }
        }

        private void UpdateTexturesPerAge()
        {
            //change castlesprite for each age.
            age = levelComponent.CurrentAge;
            if (age != oldAge)
            {
                switch (levelComponent.CurrentAge)
                {
                    case Age.Future:
                        foreach (var castlePart in castle.castleParts)
                        {
                            castlePart.UpgradeCastleParts(levelComponent.CurrentAge);
                        }
                        break;
                    case Age.Present:
                        foreach (var castlePart in castle.castleParts)
                        {
                            castlePart.UpgradeCastleParts(levelComponent.CurrentAge);
                        }
                        break;
                    case Age.Past:
                        foreach (var castlePart in castle.castleParts)
                        {
                            castlePart.UpgradeCastleParts(levelComponent.CurrentAge);
                        }
                        break;
                    default:
                        break;
                }
            }
            oldAge = age;
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            spriteBatch.Draw(background, new Rectangle(0, 0, 1280, 720), Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }

        protected override void OnEnabledChanged(object sender, EventArgs args)
        {
            Enable(castle);
            Enable(playerComponent);
            Enable(levelComponent);
            base.OnEnabledChanged(sender, args);
        }

        private void Enable(DrawableGameComponent component)
        {
            if (component != null)
            {
                component.Enabled = this.Enabled;
            }
        }

        protected override void OnVisibleChanged(object sender, EventArgs args)
        {
            Visibility(castle);
            Visibility(playerComponent);
            Visibility(levelComponent);
            
            base.OnVisibleChanged(sender, args);
        }

        private void Visibility(DrawableGameComponent component)
        {
            if (component != null)
            {
                component.Visible = this.Visible;
            }
        }
    }
}
